package cz.cvut.kadledav.paa.weight3sat.bo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static org.fest.assertions.Assertions.assertThat;

/**
 * User: David Kadlecek
 * Date: 30.12.13
 */
public class Instance implements Comparable<Instance> {
    int id;
    private int[] variablesWeight;
    private List<Variable[]> clauses = new ArrayList<>();
    private int variableWeightSum = 0;
    private final int clausesSize;
    private int knowSolution = -1;

    public int getKnowSolution() {
        return knowSolution;
    }

    public void setKnowSolution(int knowSolution) {
        this.knowSolution = knowSolution;
    }

    public Instance(int id,int numOfVariables, int clausesSize) {
        this.id = id;
        variablesWeight = new int[numOfVariables];
        this.clausesSize = clausesSize;
    }


    public void setWeights(String[] variablesWeight){
        assertThat(variablesWeight.length).isEqualTo(variablesWeight.length);
        variableWeightSum = 0;
        for (int i = 0; i < variablesWeight.length ; i++) {
            this.variablesWeight[i] = Integer.parseInt(variablesWeight[i]);
            variableWeightSum+=this.variablesWeight[i];
        }
    }

    public void setWeights(int[] variablesWeight){
        assertThat(variablesWeight.length).isEqualTo(variablesWeight.length);
        this.variablesWeight = variablesWeight;
        variableWeightSum = 0;
        for (int i = 0; i < variablesWeight.length ; i++) {
            variableWeightSum+=variablesWeight[i];
        }
    }

    /**
     * Only at instance initialize process
     * @param var1
     * @param var2
     * @param var3
     * @return
     */
    public boolean add3LiteralsToClause(int var1, int var2, int var3){
        if(clausesSize<= clauses.size()){
            return false;
        }
        Variable variable1 = new Variable(var1 < 0, Math.abs(var1) - 1);
        Variable variable2 = new Variable(var2 < 0, Math.abs(var2) - 1);
        Variable variable3 = new Variable(var3 < 0, Math.abs(var3) - 1);
        clauses.add(new Variable[]{variable1,variable2,variable3});
        return true;
    }

    public List<Variable[]> getClauses() {
        return clauses;
    }

    public int getVariableWeightSum() {
        return variableWeightSum;
    }

    public int getId() {
        return id;
    }

    public int[] getVariablesWeight() {
        return variablesWeight;
    }

    public int getNumberOfVariables(){
        return variablesWeight.length;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Instance instance = (Instance) o;

        if (clausesSize != instance.clausesSize) return false;
        if (id != instance.id) return false;
        if (variableWeightSum != instance.variableWeightSum) return false;
        if (clauses != null ? !clauses.equals(instance.clauses) : instance.clauses != null) return false;
        if (!Arrays.equals(variablesWeight, instance.variablesWeight)) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = id;
        result = 31 * result + (variablesWeight != null ? Arrays.hashCode(variablesWeight) : 0);
        result = 31 * result + (clauses != null ? clauses.hashCode() : 0);
        result = 31 * result + variableWeightSum;
        result = 31 * result + clausesSize;
        return result;
    }

    @Override
    public int compareTo(Instance o) {
        return getId() - o.getId();
    }
}
